from PySide2.QtCore import *
from PySide2.QtGui import *
import PySide2.QtGui
from PySide2.QtWidgets import *

from ui.Ui_planed_task_widget import Ui_widget_planed_task
from app.window.planed_task_new_dialog import Planed_task_new_dialog
from app.window.planed_task_editor_dialog import Planed_task_editor_dialog
from database.db import Database
import time
import datetime
from app.window.msg_box import Msg_box
from worker.tasks_worker import Task_worker
from worker.tasks_runnable import Task_runnable


class Planed_task_signal(QObject):
    open_new_task = Signal()
    remove_task = Signal()
    update_task = Signal()


class Planed_task_widget(QWidget):
        
    def __init__(self, parent=None):
        super(Planed_task_widget, self).__init__(parent)
        self.ui = Ui_widget_planed_task()
        self.ui.setupUi(self)
        self.tasks = []
        self.signal = Planed_task_signal()
        self.msg = Msg_box(self)
        self.dialog_task_new = Planed_task_new_dialog()
        self.dialog_task_new.hide()
        self.dialog_task_editor = Planed_task_editor_dialog()
        self.dialog_task_editor.hide()
        
        self.thread_pool = QThreadPool.globalInstance()
        self.thread_pool.setMaxThreadCount(10)
        self.init_work_thread()
        self.init_col_name()
        self.init_data()
        self.init_signal_slot()
        

    def __del__(self):
        print('析构函数')


    
    def init_work_thread(self):
        # 持续检测计划任务到期
        # 创建线程
        self.workerThread = QThread(self)
        self.worker = Task_worker()
        self.worker.moveToThread(self.workerThread)
        self.workerThread.started.connect(self.worker.start_work)
        self.worker.signal.finished.connect(self.workerThread.quit)
        self.worker.signal.finished.connect(self.worker.deleteLater)
        # self.worker.signal.finished.connect(Qt.BlockingQueuedConnection)
        self.worker.signal.update_next_time.connect(self.slot_update_next_time)
        self.worker.signal.update_remaining_count.connect(self.slot_update_remaining_count)
        self.worker.signal.update_timer_text.connect(self.slot_update_timer_text)
        self.worker.signal.execute_task.connect(self.slot_execute_task)
        self.workerThread.finished.connect(self.workerThread.deleteLater)
        
        self.workerThread.start()

    def slot_update_next_time(self,task_id:int,text:str):
        for i in range(len(self.tasks)):
            if self.tasks[i]['id'] == task_id:
                self.ui.tableWidget.item(i,self.col_names['下次执行时间']).setText(text)
                if text == '超时':
                    self.ui.tableWidget.item(i,self.col_names['下次执行时间']).setBackgroundColor(QColor(Qt.yellow))
                    self.ui.tableWidget.item(i,self.col_names['任务']).setBackgroundColor(QColor(Qt.yellow))
                elif text == '循环周期错误':
                    self.ui.tableWidget.item(i,self.col_names['下次执行时间']).setBackgroundColor(QColor(Qt.red))
                    self.ui.tableWidget.item(i,self.col_names['任务']).setBackgroundColor(QColor(Qt.red))
                else:
                    self.ui.tableWidget.item(i,self.col_names['下次执行时间']).setBackgroundColor(QColor(Qt.white))
                break

    def slot_update_remaining_count(self,task_id:int,count:int):
        for i in range(len(self.tasks)):
            if self.tasks[i]['id'] == task_id:
                self.ui.tableWidget.item(i,self.col_names['剩余次数']).setText(str(count))
                break
    
    def slot_update_timer_text(self,task_id:int,text:str):
        for i in range(len(self.tasks)):
            if self.tasks[i]['id'] == task_id:
                self.ui.tableWidget.item(i,self.col_names['倒计时']).setText(text)
                break

    def slot_execute_task(self,task_id:int):
        db = Database()
        data = db.select('tasks',['name','device_id','script_id'],f'id={task_id}')[0]
        device_data = db.select('devices',['ip','port','user','password','name'],f'id={data[1]}')[0]
        script_data = db.select('scripts',['content','textfsm','name'],f'id={data[2]}')[0]
        db.close_conn()
        ssh_data = {
            'id':task_id,
            'name':data[0],
            'ip':device_data[0],
            'port':device_data[1],
            'user':device_data[2],
            'password':device_data[3],
            'device_name':device_data[4],
            'cmds':script_data[0],
            'textfsm':script_data[1],
            'script_name':script_data[2],
        }
        worker = Task_runnable(ssh_data)
        self.thread_pool.start(worker)

        # 重新添加任务
        for i in range(len(self.tasks)):
            if self.tasks[i]['id'] == task_id:
                self.worker.add_task(self.tasks[i])
                break


    def init_col_name(self):
        self.col_names = {}
        # 获取列id
        max_col = self.ui.tableWidget.columnCount()
        for i in range(max_col):
            text = self.ui.tableWidget.horizontalHeaderItem(i).text()
            self.col_names[text] = i

    def init_signal_slot(self):
        self.ui.pushButton_new.clicked.connect(self.dialog_task_new.slot_show)
        self.dialog_task_new.signal.new_task.connect(self.slot_new_task)
        self.dialog_task_editor.signal.editor_task.connect(self.slot_editor_task)
        self.ui.pushButton_auto_size.clicked.connect(self.slot_btn_auto_tab_size)
        self.ui.pushButton_start_all.clicked.connect(self.slot_btn_start_all)
        self.ui.pushButton_stop_all.clicked.connect(self.slot_btn_stop_all)

    def slot_btn_start_all(self):
        checkBox_list = self.findChildren(QCheckBox)
        for check_box in checkBox_list:
            check_box.setChecked(True)

    def slot_btn_stop_all(self):
        checkBox_list = self.findChildren(QCheckBox)
        for check_box in checkBox_list:
            check_box.setChecked(False)

    def new_table_row(self,task_id:int):
        max_row = self.ui.tableWidget.rowCount()
        self.ui.tableWidget.insertRow(self.ui.tableWidget.rowCount())
        for i in range(self.ui.tableWidget.columnCount()):
            self.ui.tableWidget.setItem(max_row,i,QTableWidgetItem())
            # 单元格禁止编辑
            self.ui.tableWidget.item(max_row ,i).setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)

        opt_wid = QWidget()
        layout = QHBoxLayout(opt_wid)

        checkBox_start = QCheckBox('启动')
        btn_edit = QPushButton('编辑')
        btn_del = QPushButton('删除')

        layout.addWidget(btn_edit)
        layout.addWidget(btn_del)
        layout.setSpacing(0)
        layout.setContentsMargins(0,0,0,0)
        self.ui.tableWidget.setCellWidget(max_row,self.col_names['操作'],opt_wid)
        self.ui.tableWidget.setCellWidget(max_row,self.col_names['状态'],checkBox_start)
        
        btn_edit.clicked.connect(lambda:self.slot_show_dailog_task_editor(task_id))
        btn_del.clicked.connect(lambda:self.slot_delete_task(task_id))
        checkBox_start.stateChanged.connect(lambda check_status:self.slot_checkBox_start(task_id,check_status))


    def slot_show_dailog_task_editor(self,task_id:int):
        checkBox_list= self.findChildren(QCheckBox)
        for i in range(len(checkBox_list)):
            if self.tasks[i]['id'] == task_id and checkBox_list[i].isChecked():
                self.msg.msg_tips('启用状态,不可编辑')
                return
        self.dialog_task_editor.slot_show(task_id)


    def slot_checkBox_start(self,task_id:int,check_status:int):
        '''
            自定义选项开关槽函数
        '''
        if check_status == Qt.Checked:
            data = {}
            for i in range(len(self.tasks)):
                if self.tasks[i]['id'] == task_id:
                    data = self.tasks[i]
                    self.ui.tableWidget.item(i,self.col_names['任务']).setBackgroundColor(QColor(Qt.green))
                    break
            if len(data) <= 0: return
            self.worker.add_task(data)

        else:
            self.worker.remove_task(task_id)
            for i in range(len(self.tasks)):
                if self.tasks[i]['id'] == task_id:
                    self.ui.tableWidget.item(i,self.col_names['下次执行时间']).setText('')
                    self.ui.tableWidget.item(i,self.col_names['剩余次数']).setText('')
                    self.ui.tableWidget.item(i,self.col_names['倒计时']).setText('')
                    self.ui.tableWidget.item(i,self.col_names['下次执行时间']).setBackgroundColor(QColor(Qt.white))
                    self.ui.tableWidget.item(i,self.col_names['任务']).setBackgroundColor(QColor(Qt.white))
                    break


    def slot_new_task(self,task_id:int):
        #获取数据
        db = Database()
        fields = ['name','device_id','script_id','start_time','exec_times','loop_day','loop_hour']
        task_data = db.select('tasks',fields,f'id={task_id}')[0]
        data = {
            'id':task_id,
            'name':task_data[0],
            'device_id':task_data[1],
            'script_id':task_data[2],
            'start_time':task_data[3],
            'exec_times':str(task_data[4]),
            'loop_day':str(task_data[5]),
            'loop_hour':str(task_data[6]),
            
        }
        self.tasks.append(data)

        # 写入ui数据
        self.new_table_row(task_id) #新建一行
        row = self.ui.tableWidget.rowCount() - 1
        #id name
        self.ui.tableWidget.item(row,self.col_names['id']).setText(str(data['id']))
        self.ui.tableWidget.item(row,self.col_names['任务']).setText(data['name'])
        # 设备
        device_data = db.select('devices',['name','ip'],f'id={data["device_id"]}')[0]
        self.ui.tableWidget.item(row,self.col_names['设备']).setText(device_data[0])
        self.ui.tableWidget.item(row,self.col_names['ip']).setText(device_data[1])
        # 脚本
        scrip_name = db.select('scripts',['name'],f'id={data["script_id"]}')[0][0]
        self.ui.tableWidget.item(row,self.col_names['Script']).setText(scrip_name)
        # 定时启动
        self.ui.tableWidget.item(row,self.col_names['定时启动']).setText(data['start_time'])
        # 执行次数
        self.ui.tableWidget.item(row,self.col_names['执行次数']).setText(data['exec_times'])
        # 循环周期
        lool_interval = f"{data['loop_day']}天{data['loop_hour']}时" 
        self.ui.tableWidget.item(row,self.col_names['循环周期']).setText(lool_interval)


    def init_data(self):
        # 清理现有行
        row_count = self.ui.tableWidget.rowCount()
        for row in range(row_count,-1,-1):
            self.ui.tableWidget.removeRow(row)
        # 清理线程检测
        self.worker.clear_work()
        #获取tasks
        db = Database()
        tasks_id_list = db.select('tasks',['id'])
        db.close_conn()
        # 加载新数据
        for ids in tasks_id_list:
            self.slot_new_task(ids[0])

        self.slot_btn_auto_tab_size()




    def slot_btn_auto_tab_size(self):
        self.ui.tableWidget.resizeColumnsToContents() #自动列宽
        self.ui.tableWidget.resizeRowsToContents() #自动行高
        # 最后一行自动填充
        self.ui.tableWidget.horizontalHeader().setSectionResizeMode(self.ui.tableWidget.columnCount()-1,QHeaderView.Stretch)
    

    def slot_delete_task(self,task_id:int):
        if not self.msg.msg_is_ok_cancel('确定删除?'):
            return
        # 删除工作线程任务
        self.worker.remove_task(task_id)
        # 获取行号
        row = -1
        for i in range(len(self.tasks)):
            if self.tasks[i]['id'] == task_id:
                row = i
                break
        if i >= 0:
            del self.tasks[row]
            self.ui.tableWidget.removeRow(row)
        # 删除数据库信息
        db = Database()
        db.delete('tasks',f'id={task_id}')
        db.close_conn()
        

    def slot_editor_task(self,task_id:int):
        # 软件数据更新
        db = Database()
        fields = ['name','device_id','script_id','start_time','exec_times','loop_day','loop_hour',]
        task_data = db.select('tasks',fields,f'id={task_id}')[0]
        data = {
            'id':task_id,
            'name':task_data[0],
            'device_id':task_data[1],
            'script_id':task_data[2],
            'start_time':task_data[3],
            'exec_times':str(task_data[4]),
            'loop_day':str(task_data[5]),
            'loop_hour':str(task_data[6]),
        }
        row = -1
        for i in range(len(self.tasks)):
            if self.tasks[i]['id'] == task_id:
                row = i
                break
        if row < 0 : return
        self.tasks[row] = data

        # 更新ui数据
        # 名称
        self.ui.tableWidget.item(row,self.col_names['任务']).setText(data['name'])
        # 设备
        device_data = db.select('devices',['name','ip'],f'id={data["device_id"]}')[0]
        self.ui.tableWidget.item(row,self.col_names['设备']).setText(device_data[0])
        self.ui.tableWidget.item(row,self.col_names['ip']).setText(device_data[1])
        # 脚本
        scrip_name = db.select('scripts',['name'],f'id={data["script_id"]}')[0][0]
        self.ui.tableWidget.item(row,self.col_names['Script']).setText(scrip_name)
        # 定时启动
        self.ui.tableWidget.item(row,self.col_names['定时启动']).setText(data['start_time'])
        # 执行次数
        self.ui.tableWidget.item(row,self.col_names['执行次数']).setText(data['exec_times'])
        # 循环周期
        lool_interval = f"{data['loop_day']}天{data['loop_hour']}时" 
        self.ui.tableWidget.item(row,self.col_names['循环周期']).setText(lool_interval)

        db.close_conn()


